package com.example.response.controller;

import com.example.response.annotation.NotReturnResultVO;
import com.example.response.entity.User;
import com.example.response.exception.ApiException;
import com.example.response.vo.ResultVO;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@Api(value = "用户接口")
@Slf4j
@RestController
public class UserController {

    @ApiOperation(value = "用户新增功能第一版", notes = "用户新增功能第一版")
    @GetMapping("/addUser01")
    public String addUser01(User user){
        if(user == null|| user.getId() == 0 || user.getNickName() == null || user.getEmail() == null){
            return "用户及用户字段不能为空";
        }
        if(user.getNickName().length() < 6 || user.getNickName().length() > 12){
            return "用户名长度不能小于6位且不能大于12位";
        }
        if(!user.getEmail().endsWith("@easemob.com")){
            return "请输入环信邮箱";
        }
        return "用户数据新增成功";
    }

    /**进化：
     * BindingResult和@Valid+实体类的注解校验，解决代码块里过多判断逻辑问题。
     * BindingResult用在实体类校验信息返回结果绑定。@Valid和BindingResult配套使用，@Valid用在参数前，BindingResult作为校验结果绑定返回
     * bindingResult.hasErrors()判断是否校验通过，校验未通过，bindingResult.getFieldError().getDefaultMessage()获取在TestEntity的属性设置的自定义message，
     *  如果没有设置，则返回默认值"javax.validation.constraints.XXX.message"。
     * 注意：在实体类使用校验注解时，controller一定要使用bindingResult处理校验结果，且实体类作为查询参数时，避免被其他方法使用，不然有的地方需要限制，有的没有，不需要限制的方法会报错。
     * @param user
     * @param bindingResult
     * @return
     */
    @ApiOperationSupport(order = 0, author = "dangwen")
    @GetMapping("/addUser02")
    public String addUser02(@Valid User user, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
//            String defaultMessage = bindingResult.getFieldError().getDefaultMessage();
            String defaultMessage = "";
            for(FieldError fieldError : bindingResult.getFieldErrors()){
                defaultMessage += fieldError.getDefaultMessage()+" ";
            }
            return defaultMessage;
        }
        return "用户数据新增成功";
    }

    /**进化：
     * 使用springboot全局异常处理Exception
     * 使用ApiException自定义异常类处理RuntimeException
     * 使用ResultVo<T>处理响应体的统一问题
     * @param user
     * @return
     */
    @ApiOperation(value = "用户新增接口第三版", notes = "用户新增接口第三版")
    @GetMapping(value = "/addUser03")
    public ResultVO<User> addUser03(@Valid User user){
        if(!user.isAdult()){
            throw new ApiException(-1,"未成年");
        }
        return new ResultVO<>(user);
    }

    /**进化：
     * 解决每一个接口返回数据时都要用响应体来包装的问题吗，简化代码
     * @param user
     * @return
     */
    @ApiResponses(value = {
            @ApiResponse(code = 0000,message = "新增成功"),
            @ApiResponse(code = 9999, message = "新增失败")
    })
    @GetMapping(value = "/addUser04")
    public User addUser04(@Valid User user){
        if(!user.isAdult()){
            throw new ApiException(-1,"未成年04");
        }
        return user;
    }

    /**进化：
     * @NotReturnResultVO 添加了该注解后，不再返回ResultVO封装的数据，只返回元数据
     * @param user
     * @return
     */
    @ApiImplicitParams({
            @ApiImplicitParam(name = "user", value = "用户对象", required = true, dataType = "json", paramType = "User", example = "{'id':1}")
    })
    @GetMapping(value = "/addUser05")
    @NotReturnResultVO
    public User addUser05(@Valid User user){
        if(!user.isAdult()){
            throw new ApiException(-1,"未成年04");
        }
        return user;
    }

    //测试返回结果为String类型的情况
    @GetMapping("stringTest")
    public String stringTest(){
        return "123456789";
    }

    //测试返回结果为ResultVO类型的情况
    @GetMapping("resultvoTest")
    public ResultVO resultvoTest(){
        return new ResultVO("1");
    }
}
